from vectors import scale, add, to_polar, to_cartesian
from teapot import load_triangles
from draw_model import draw_model
from math import pi

def scale2(v):
    return scale(2.0, v)

def translate1left(v):
    return add((-1, 0, 0), v)

def scale2_then_translate1left(v):
    return translate1left(scale2(v))

def compose(f1, f2):
    def new_function(input):
        return f1(f2(input))
    return new_function

def polygon_map(transformation, polygons):
    return [
        [transformation(vertex) for vertex in triangle]
        for triangle in polygons
    ]

def rotate2d(angle, vector):
    l,a = to_polar(vector)
    return to_cartesian((l, a+angle))

def rotate_z(angle, vector):
    x,y,z = vector
    new_x, new_y = rotate2d(angle, (x,y))
    return new_x, new_y, z

def rotate_z_by(angle):
    def new_function(v):
        return rotate_z(angle, v)
    return new_function

def rotate_x(angle, vector):
    x,y,z = vector
    new_y, new_z = rotate2d(angle, (y,z))
    return x, new_y, new_z

def rotate_x_by(angle):
    def new_function(v):
        return rotate_x(angle,v)
    return new_function

def stretch_x(v):
    x,y,z = v
    return (4*x, y, z)

def stretch_y(v):
    x,y,z = v
    return (x, 4*y, z)

def cube_stretch_y(v):
    x,y,z = v
    return (x, y*y*y, z)

def slant_xy(vector):
    x,y,z = vector
    return (x+y, y, z)

# original_triangles = load_triangles()

# transformed_triangles = [
#     [scale2(vertex) for vertex in triangle] 
#     for triangle in original_triangles
# ]

# transformed_triangles = [
#     [translate1left(scale2(vertex)) for vertex in triangle]
#     for triangle in original_triangles
# ]

# transformed_triangles = [
#     [scale2(translate1left(vertex)) for vertex in triangle]
#     for triangle in original_triangles
# ]

# draw_model(transformed_triangles)

# draw_model(polygon_map(rotate_z_by(pi/4.),  load_triangles()))
# draw_model(polygon_map(rotate_x_by(pi/2.),  load_triangles()))

# draw_model(polygon_map(stretch_x,  load_triangles()))
# draw_model(polygon_map(stretch_y,  load_triangles()))
# draw_model(polygon_map(cube_stretch_y,  load_triangles()))
# draw_model(polygon_map(slant_xy,  load_triangles()))

# 练习4.1
def translate_by(translation):
    def new_function(v):
        return add(translation, v)
    return new_function

# 练习4.2
# draw_model(polygon_map(translate_by((0, 0, -20)),  load_triangles()))

# 练习4.3
def scale_by(scaling):
    def new_function(v):
        return scale(scaling, v)
    return new_function

# draw_model(polygon_map(scale_by(0.5), load_triangles()))
# draw_model(polygon_map(scale_by(-1), load_triangles()))

# 练习4.6
def compose(*args):
    def new_function(input):
        state = input
        for f in reversed(args):
            state = f(state)
        return state
    return new_function

# 练习4.7
def curry2(f):
    def g(x):
        def new_function(y):
            return f(x,y)
        return new_function
    return g

# 练习4.8
# draw_model(load_triangles())
# draw_model(polygon_map(rotate_z_by(pi/2), load_triangles()))
# draw_model(polygon_map(compose(rotate_z_by(pi/2),rotate_x_by(pi/2)), load_triangles()))
# draw_model(polygon_map(compose(rotate_x_by(pi/2),rotate_z_by(pi/2)), load_triangles()))
# ？？？这个组合相当于绕[插图]轴顺时针旋转π/2弧度。颠倒顺序，则是绕[插图]轴逆时针旋转π/2弧度。